/*
 * @Author: FanWeiHua
 * @Date: 2021-05-26 19:16:19
 * @LastEditTime: 2021-07-28 10:04:43
 * @Description: plugins
 */
'use strict';
const exec = require('child_process').execSync;
const units = require('../nodeServer/units');
const path = require('path');
const webpack = require('webpack');
const CopyPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 每次构建前清理webpack配置的output目录，这样只会生成用到的文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 将CSS提取到单独的文件中 它为每个包含CSS的JS文件创建一个CSS文件 它支持CSS和SourceMap的按需加载
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); // 对CSS进行压缩
const CompressionPlugin = require('compression-webpack-plugin'); // 压缩资源
const { VueLoaderPlugin } = require('vue-loader');
const DoneWebpackPlugin = require('done-webpack-plugin');
const WebpackBar = require('webpackbar');
const { isConfig, logColor, isFile } = require('./util');
const ErrorOverlayPlugin = require('error-overlay-webpack-plugin'); // 错误信息在页面展示
/**
 * webpack的自定义配置
 */
const webpackConfig = JSON.parse(process.env.webpackConfig);
/**
 * 获取当前项目的配置文件状态
 */
const configState = isConfig(`${webpackConfig.project.path}/config`);
/**
 * 需要拷贝的静态资源
 */
const CopyPluginPatterns = [
  // 配置文件拷贝
  {
    from: `${webpackConfig.project.path}/config/system.${
      process.env.NODE_ENV === 'local' || process.env.NODE_ENV === 'prod-dev' ? 'prod' : process.env.NODE_ENV
    }.config.js`,
    to: `./config/systemConfig.js`
  }
];
module.exports = () => {
  /**
   * 基础插件模块
   */
  const modePlugins = [new WebpackBar(), new VueLoaderPlugin()];
  /**
   * 开发模式
   */
  const dev = () => {
    modePlugins.push(
      new webpack.HotModuleReplacementPlugin() // HMR 热替换模块 开发模式搭配WDS WDM使用
    );
    // 报错异常在页面展示
    modePlugins.push(new ErrorOverlayPlugin());
    // 如果存在配置文件，则需要拷贝
    if (configState) {
      modePlugins.push(
        new CopyPlugin({
          patterns: CopyPluginPatterns,
          options: {
            concurrency: 100 // limits the number of simultaneous requests to fs
          }
        })
      );
    }
  };
  /**
   * 打包模式
   */
  const build = () => {
    // 判断是否存在抽象出来的静态资源
    const excludeStaticPath = `${webpackConfig.project.path}/excludeStatic`;
    const excludeStaticState = isFile(excludeStaticPath);
    if (excludeStaticState) {
      CopyPluginPatterns.push({
        from: excludeStaticPath, // static resource directory
        to: './excludeStatic'
      });
    }
    // 如果存在配置文件，则需要拷贝
    if (configState) {
      modePlugins.push(
        new CopyPlugin({
          patterns: CopyPluginPatterns,
          options: {
            concurrency: 100 // limits the number of simultaneous requests to fs
          }
        })
      );
    }
    modePlugins.push(
      new CleanWebpackPlugin(),
      new CssMinimizerPlugin(),
      new CompressionPlugin({
        filename: '[path][base].gz', // 目标资源名称。[file] 会被替换成原资源。[path] 会被替换成原资源路径，[query] 替换成原查询字符串
        algorithm: 'gzip',
        test: new RegExp(
          '\\.(js|css)$' // 压缩 js css
        ),
        threshold: 10240, // 只处理比这个值大的资源。按字节计算
        minRatio: 0.8 // 只有压缩率比这个值小的资源才会被处理
      }),
      /**
       * 打包完成
       */
      new DoneWebpackPlugin(stats => {
        const distUrl = path.join(__dirname, `../../dist/${webpackConfig.project.name}`); // dist文件夹
        /**
         * 替换服务，主要是为了替换已抽离图片访问路径的字符
         */
        if (excludeStaticState) {
          units.replaceSpecialString(distUrl, webpackConfig.publicPath);
        }
        /**
         * dist文件夹压缩服务
         */
        units.zipFolderServer(distUrl, `${webpackConfig.project.name}.zip`);
        console.log(logColor('green'), `打包输出的项目地址：${distUrl}`);
        /**
         * 如果是mac操作系统，打开dist项目目录
         */
        if (process.platform === 'darwin') {
          exec(`open ${path.join(__dirname, '../../dist/')}`);
        } else {
          exec(`explorer.exe ${path.join(__dirname, '../../dist/')}`);
        }
      })
    );
  };
  /**
   * 插件模式
   */
  const modePluginsNode = {
    // 开发模式
    dev: () => {
      dev();
    },
    // 打包模式
    build: () => {
      build();
      modePlugins.push(
        new MiniCssExtractPlugin({
          filename: './static/css/[name]-[id].[chunkhash:8].bundle.css' // 指定打包后的css
        }) // 用来抽离css文件 不用打包到js文件里
      );
    },
    // 本地模式
    local: () => {
      build();
    }
  };
  if (process.env.NODE_ENV === 'dev') {
    modePluginsNode.dev();
  } else if (process.env.NODE_ENV === 'local') {
    modePluginsNode.local();
  } else {
    modePluginsNode.build();
  }
  return [].concat(modePlugins);
};
